﻿using CSRedis;
using furion.blog.Web.Core.Filters;
using furion.blog.Web.Core.Handlers;
using furion.blog.Web.Core.Middleware;
using Furion;
using Masuit.Tools.Config;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Newtonsoft.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System;
using Furion.FriendlyException;
using MongoDB.Driver;
using Microsoft.AspNetCore.Server.Kestrel.Core;

namespace furion.blog.Web.Core;

public class Startup : AppStartup
{
    
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton(InitRedis());
        services.AddSingleton(InitMongoDB());

        services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);

        services.AddMvc((options) =>
        {
            options.Filters.Add(typeof(RequestFilter));
            options.Filters.Add(typeof(ExceptionHandler));
            options.Filters.Add(typeof(ValidateModelAttributeFilter));
        });

        services.AddCorsAccessor();

        //添加sqlsuager
        services.AddSqlsugarSetup(App.Configuration);

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        // Add detection services container and device resolver service.
        services.AddDetection();

        App.Configuration.AddToMasuitTools();

        //配置可以同步请求读取流数据
        services.Configure<KestrelServerOptions>(x => x.AllowSynchronousIO = true)
            .Configure<IISServerOptions>(x => x.AllowSynchronousIO = true);

        //开启定时任务
        services.AddTaskScheduler();

        services
            .AddControllersWithViews()
            .AddNewtonsoftJson(options => {
                //忽略循环引用
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                //时间格式
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
                options.SerializerSettings.ContractResolver = new CustomContractResolver();
            })
            .AddJsonOptions(options => {
                //忽略循环引用
                options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
                //时间格式
                options.JsonSerializerOptions.Converters.AddDateFormatString("yyyy-MM-dd HH:mm:ss");
            })
            .AddFriendlyException()
            .AddInject();
        //.AddInjectWithUnifyResult();

        services.AddSingleton<IHostedService, LifetimeEventsHostedService>();

    }

    /// <summary>
    /// 初始化mongodb
    /// </summary>
    /// <returns></returns>
    private async Task InitMongoDB() {
        try
        {
            var db = App.Configuration["Mongo:DB"];
            var connStr = App.Configuration["Mongo:Connection"];
            await MongoDB.Entities.DB.InitAsync(db, MongoClientSettings.FromConnectionString(connStr));
        }
        catch (Exception ex) {
            throw Oops.Oh("mongodb连接失败!!!");
        }
    }

    /// <summary>
    /// 初始化Redis缓存
    /// </summary>
    private CSRedisClient[] InitRedis()
    {
        //redis缓存
        //var section = App.Configuration["Redis:Default"];
        //连接字符串
        string _connectionString = App.Configuration["Redis:Default:Connection"];
        //默认数据库
        int _defaultDB = int.Parse(App.Configuration["Redis:Default:DefaultDB"] ?? "0");
        //超时时间
        int _idleTimeout = int.Parse(App.Configuration["Redis:Default:IdelTimeout"] ?? "0");
        //线程池数量
        int _poolSize = int.Parse(App.Configuration["Redis:Default:PoolSize"] ?? "50");

        var css = new CSRedisClient[16];

        for (int i = 0; i <= 15; i++)
        {
            var redis = new CSRedis.CSRedisClient($"{_connectionString},defaultDatabase={i},idleTimeout={_idleTimeout},poolsize={_poolSize},prefix=");
            RedisHelper.Initialization(redis);
            css[i] = redis;
        }

        return css;
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }


        //允许body重用
        app.Use(next => new RequestDelegate(
          async context =>
          {
              context.Request.EnableBuffering();
              await next(context);
          }
        ));

        app.UseHttpsRedirection();
        app.UseDetection();
        app.UseStaticFiles();
        app.UseSerilogRequestLogging();//记录请求日志 必须在 UseStaticFiles 和 UseRouting 之间
        app.UseRouting();

        app.UseCorsAccessor();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseInject();

        app.UseMiddleware<RealIpMiddleware>();

        //初始化MQ消费者
        new furion.blog.Application.KafkaMQ.Consumers.AliSmsSendRecordConsumer(env);
        new furion.blog.Application.KafkaMQ.Consumers.WxSendMsgToMemberConsumer(env);

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });

        

    }
}
